package com.hex.es.aop;

import com.google.common.collect.Maps;
import com.hex.es.annotation.EsBuildParamTypeInfo;
import com.hex.es.component.ParamTypeRouter;
import com.hex.es.component.ReturnSearchRouter;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.context.ApplicationContext;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Map;

/**
 * @ClassName EsInvocationHandler
 * @Description EsInvocationHandler
 * @Author hex
 * @Date 2020/12/18 18:12
 * @Version 1.0
 */
@Slf4j
public class EsInvocationHandler extends AbstractEsAop implements InvocationHandler {

    private ApplicationContext applicationContext;

    EsInvocationHandler(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder);
        EsBuildParamTypeInfo esBuildParamTypeInfo = method.getAnnotation(EsBuildParamTypeInfo.class);
        try {
            //构建本次查询的全局参数传递池
            Map<String, Object> map = Maps.newConcurrentMap();
            PARAM_THREAD_LOCAL.set(map);

            Parameter[] parameters = method.getParameters();
            for (int i = 0; i < args.length; i++) {
                applicationContext.getBean(ParamTypeRouter.class).route(parameters[i].getName(), args[i], boolQueryBuilder, searchQueryBuilder, method.getAnnotation(EsBuildParamTypeInfo.class));
            }
        } finally {
            PARAM_THREAD_LOCAL.remove();
        }
        typeIndexHandler(esBuildParamTypeInfo, searchQueryBuilder);
        return applicationContext.getBean(ReturnSearchRouter.class).route(method,esBuildParamTypeInfo,searchQueryBuilder.build());
    }

    /**
     * 索引、类型处理方法
     * @param esBuildParamTypeInfo
     * @param searchQueryBuilder
     */
    private void typeIndexHandler(EsBuildParamTypeInfo esBuildParamTypeInfo, NativeSearchQueryBuilder searchQueryBuilder) {
        if (esBuildParamTypeInfo.types().length > 0) {
            searchQueryBuilder.withTypes(esBuildParamTypeInfo.types());
        }
        if (esBuildParamTypeInfo.indexs().length > 0) {
            searchQueryBuilder.withIndices(esBuildParamTypeInfo.indexs());
        }
    }
}
